package org.quickjsf.core.base.controller;

import java.util.List;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.component.menuitem.MenuItem;
import org.primefaces.model.DefaultMenuModel;
import org.primefaces.model.MenuModel;
import org.quickjsf.common.util.DomainUtil;
import org.quickjsf.common.util.FacesUtil;
import org.quickjsf.core.base.QuickJsfContainer;
import org.quickjsf.core.base.dao.PageModel;
import org.quickjsf.core.base.service.IBaseService;
import org.quickjsf.core.base.viewmodel.BaseDTPanelViewModel;
import org.quickjsf.core.base.viewmodel.vo.ColumnModel;
import org.quickjsf.core.base.viewmodel.vo.FieldFilter;
import org.quickjsf.core.datamodel.IDataModel;
import org.quickjsf.core.datamodel.OptionType;

public class BaseDTPanelController<T> implements IDataModel<T>{
	
	protected MenuModel menuModel;
	protected UIComponent datatTablePanel;	
	protected List<ColumnModel> columns;
	protected Map<String, List<OptionType>> optionTypes;
	
	protected BaseDTPanelViewModel<T> viewModel;
	
	protected IBaseService<T> service;
	
	protected QuickJsfContainer quickJsfContainer;


	public static final String LIST_FORM_ID = "list_form";
	public static final String DATATABLE_ID = "data_table";
	public static final String MSG_GROWL_ID = "msg_growl";
	public static final String QUICKJSF_CONTAINER_ID = "quickJsf";
	
	
	public BaseDTPanelController(BaseDTPanelViewModel<T> viewModel) throws Exception {
		this.viewModel = viewModel;
		initDatatablePanel();
	}
	
	/**
	 * init DatatablePanel
	 * @throws Exception
	 */
	protected void initDatatablePanel() throws Exception {
		quickJsfContainer = (QuickJsfContainer) FacesUtil.getManagedBean(QUICKJSF_CONTAINER_ID);
		columns = quickJsfContainer.getColumnModelMap().get(viewModel.getEntityCls().getSimpleName());
		optionTypes = quickJsfContainer.getOptionTypeMap().get(viewModel.getEntityCls().getSimpleName());
	}
	
	public final String getManageBeanName() {
		return FacesUtil.getManagedBeanName(this.getClass());
	}
	
	public final String getFieldOptionTypesValueEL(String field) {
		return "#{"+getManageBeanName()+".optionTypes['"+field+"']}";
	}
	
	/*****************************************IDataModel implements*****************************************/
	@Override
	public T getModel(String id) {
		return service.fetchAllById(id);
	}
	
	@Override
	public PageModel<T> getPageModel(int first, int pageSize, String sortField,
			String sortName, List<FieldFilter> filters) {
		return service.getTableFilterList(first, pageSize, sortField, sortName, filters);
	}
	
	/**
	 * 重置数据表格
	 */
	public void resetDataTable() {
		DataTable dataTable = (DataTable) FacesUtil.getUIComponent(getFullDataTableId());
		dataTable.reset();
		//default sortBy id
		dataTable.setValueExpression("sortBy",
				FacesUtil.createObjValueExpression(dataTable.getVar()+"."+DomainUtil.getFieldId(viewModel.getEntityCls())));
	}

	public final String getFullDataTableId() {
		StringBuffer fullDatatableId = new StringBuffer();
		fullDatatableId.append(getFullListFormId());
		fullDatatableId.append(FacesUtil.getSeparatorChar());
		fullDatatableId.append(DATATABLE_ID);
		return fullDatatableId.toString();
	}
	

	public final String getFullListFormId() {
		StringBuffer fullListFormId = new StringBuffer();
		fullListFormId.append(getDatatablePanelClientId());
		fullListFormId.append(FacesUtil.getSeparatorChar());
		fullListFormId.append(LIST_FORM_ID);
		return fullListFormId.toString();
	}
	
	public final String getFullMsgGrowlId() {
		StringBuffer fullListFormId = new StringBuffer();
		fullListFormId.append(getDatatablePanelClientId());
		fullListFormId.append(FacesUtil.getSeparatorChar());
		fullListFormId.append(MSG_GROWL_ID);
		return fullListFormId.toString();
	}
	
	public void addMenuBarItem(MenuModel menuModel) {}
	
	private void addMenuBarItem() {
		menuModel = new DefaultMenuModel();  
		//用户自定义MenuBarItem
		addMenuBarItem(menuModel);
	}
	
	public final MenuItem createSimpleMenuItem(String id, String value, String url, String icon) {
		MenuItem menuItem = new MenuItem();
		menuItem.setId(id);
		menuItem.setValue(value);
		if (!StringUtils.isEmpty(url)) {
			menuItem.setUrl(url);
		}
		if (!StringUtils.isEmpty(icon)) {
			menuItem.setIcon(icon);
		}
		return menuItem;
	}
	
	public final MenuItem createActionMenuItem(String id, String value, 
			String actionListener, String icon, String update, String oncomplete, String process) {
		MenuItem menuItem = new MenuItem();
		menuItem.setId(id);
		if (value.startsWith("#{")) {
			menuItem.setValueExpression("value", FacesUtil.createValueExpression(value));
		} else {
			menuItem.setValue(value);
		}
		if (!StringUtils.isEmpty(actionListener)) {
			if (actionListener.startsWith("#{")) {
				menuItem.addActionListener(FacesUtil.createActionListener(actionListener));
			} else {
				menuItem.addActionListener(FacesUtil.createActionListener("#{"+getManageBeanName()+"."+actionListener+"}"));
			}
		}
		//update attr
		if (!StringUtils.isEmpty(update)) {
			menuItem.setUpdate(update + " " + FacesUtil.getSeparatorChar()+getFullMsgGrowlId());
		} else {
			menuItem.setUpdate(FacesUtil.getSeparatorChar()+getFullMsgGrowlId());
		}
		//oncomplete attr
		if (!StringUtils.isEmpty(oncomplete)) {
			menuItem.setOncomplete(oncomplete);
		}
		//icon attr
		if (!StringUtils.isEmpty(icon)) {
			menuItem.setIcon(icon);
		}
		//process attr 默认处理行选中
		String defaultProcess = "@this "+ FacesUtil.getSeparatorChar() + getFullDataTableId();
		if (!StringUtils.isEmpty(process)) {
			process =defaultProcess + " " + process;
		} else {
			process = defaultProcess;
		}
		menuItem.setProcess(process);
//		menuItem.setImmediate(immediate);
		
		return menuItem;
	}
	
	public final MenuItem createSelectSupportMenuItem(String value, String icon, String update, String oncomplete) {
		MenuItem menuItem = new MenuItem();
		if (value.startsWith("#{")) {
			menuItem.setValueExpression("value", FacesUtil.createValueExpression(value));
		} else {
			menuItem.setValue(value);
		}
		
		menuItem.addActionListener(FacesUtil.createActionListener("#{"+getManageBeanName()+".editableDTPanelSupport.setUpdateRow}"));
		
		if (!StringUtils.isEmpty(update)) {
			menuItem.setUpdate(update + " " + FacesUtil.getSeparatorChar()+getFullMsgGrowlId());
		} else {
			menuItem.setUpdate(FacesUtil.getSeparatorChar()+getFullMsgGrowlId());
		}
		if (!StringUtils.isEmpty(oncomplete)) {
			menuItem.setOncomplete(oncomplete);
		}
		if (!StringUtils.isEmpty(icon)) {
			menuItem.setIcon(icon);
		}
		menuItem.setProcess(FacesUtil.getSeparatorChar() + getDatatablePanelClientId());
		return menuItem;
	}
	
	/**
	 * 获得DatatablePanel复合组件的clientId
	 * @return
	 */
	public String getDatatablePanelClientId() {
//		String id = FacesUtil.getRequestParameter("javax.faces.source").split("-")[0] + "-";
		return datatTablePanel.getClientId();
	}
	
	public List<ColumnModel> getColumns() {
		return columns;
	}

	public void setColumns(List<ColumnModel> columns) {
		this.columns = columns;
	}

	public Map<String, List<OptionType>> getOptionTypes() {
		return optionTypes;
	}

	public BaseDTPanelViewModel<T> getViewModel() {
		return viewModel;
	}

	public void setViewModel(BaseDTPanelViewModel<T> viewModel) {
		this.viewModel = viewModel;
	}

	public MenuModel getMenuModel() {
		addMenuBarItem();
		return menuModel;
	}

	public void setMenuModel(MenuModel menuModel) {
		this.menuModel = menuModel;
	}

	public UIComponent getDatatTablePanel() {
		return datatTablePanel;
	}

	public void setDatatTablePanel(UIComponent datatTablePanel) {
		this.datatTablePanel = datatTablePanel;
	}

	public IBaseService<T> getService() {
		return service;
	}

	public void setService(IBaseService<T> service) {
		this.service = service;
	}	
	
	public QuickJsfContainer getQuickJsfContainer() {
		return quickJsfContainer;
	}
}
